﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Autofac;
using KJSyncXP.Extensions;
using KJSyncXP.SQLite.Context;
using KJSyncXP.Oracle.Context; 
using log4net;
using KJSyncXP.Sqlite.Model;
using FreeSql;
using KJSyncXP.Oracle.Model;
using System.Windows.Automation.Peers;
using AutoMapper;
using System.Data;
using System.Data.Common;

namespace KJSyncXP.Services
{
    /// <summary>
    /// SQLiteOracle同步服务
    /// </summary>
    public class OracleSqliteSyncService
    {
        private readonly ILog _logger;

        private readonly CrcCalculator _crcCalculator = new CrcCalculator();

        private readonly AppConfig _appConfig;

        private const string __REMOTE_SYNC_STATE_PENDING = "PENDING";

        private const string __REMOTE_SYNC_STATE_COMPLETE = "COMPLETE";


        // Oracle 事务对象
        DbTransaction oracleTrans = null;
        // SQLite 事务对象
        DbTransaction sqliteTrans = null;

        /// <summary>
        /// 构造函数（注入日志）
        /// </summary>
        public OracleSqliteSyncService(ILog log, AppConfig appConfig)
        {
            _logger = log;
            _appConfig = appConfig;
        }

        #region 从MES同步标准数据到Sqlite
        /// <summary>
        /// 获取MES的测试标准表同步到本地Sqlite
        /// </summary>
        public void GetMesTestStandard()
        {
            // 拉取Mes同步状态为PENDING的
            _logger.Info($"开始同步KJ_TEST_STANDARD检测标准表，同步时间" + DateTime.Now);

            using (var scope = App._container.BeginLifetimeScope())
            {
                var oracleCtx = scope.Resolve<OracleDbContext>();
                var sqliteCtx = scope.Resolve<SqliteDbContext>();

                // 拉取当前机台号的标准
                var mesTestStandard = oracleCtx.Db.Queryable<KJ_TEST_STANDARD>()
                         .Where(item => item.RECEIVE_FLAG == "PENDING" && item.EQP == _appConfig.DetectionMachineNo)
                         .ToList();

                if (!mesTestStandard.Any())
                {
                    return;
                }
                else
                {
                    //查询本地sqlite有没有guid相同的数据，如果有则更新，没有则新增
                    AutoMapperConfig.Init();
                    var sqliteMesTestStandard = Mapper.Map<List<Sqlite_KJ_TEST_STANDARD>>(mesTestStandard);

                    var existingGuidsInSqlite = sqliteCtx.Db.Queryable<Sqlite_KJ_TEST_STANDARD>()
                        .ToList()
                        .Select(item => item.GUID).ToList();

                    var dataToInsert = sqliteMesTestStandard
                        .Where(item => !existingGuidsInSqlite.Contains(item.GUID)) // GUID 不在本地 → 新增
                        .ToList();

                    var dataToUpdate = sqliteMesTestStandard
                        .Where(item => existingGuidsInSqlite.Contains(item.GUID)) // GUID 在本地 → 更新
                        .ToList();

                
                    // 处理新增,修改
                    if (dataToInsert.Any())
                    {
                        var insertRows = sqliteCtx.Db.Insert<Sqlite_KJ_TEST_STANDARD>()
                            .AppendData(dataToInsert)
                            .ExecuteAffrows();
                    }

                    if (dataToUpdate.Any())
                    {
                        dataToUpdate.ForEach(item => item.RECEIVE_DATE = DateTime.Now);

                        // 批量更新：通过 Where 条件匹配 GUID，确保只更新对应记录
                        var updateRows = sqliteCtx.Db.Update<Sqlite_KJ_TEST_STANDARD>()
                            .SetSource(dataToUpdate) // 待更新的数据源
                            .UpdateColumns(item => new  // 明确需要更新的业务字段（排除 GUID）
                            {
                                item.TEST_PROJECT,
                                item.EQP,
                                item.MIN_DATA,
                                item.MAX_DATA,
                                item.START_DATE,
                                item.END_DATE,
                                item.RECEIVE_FLAG,
                                item.RECEIVE_DATE,
                            })
                            .ExecuteAffrows();
                    }                    
                }
            }
        }
        #endregion


        #region 同步本地sqlite中硫变仪检测数据到Oracle

        public void PullDatRH200ToMes()
        {
            try {
                _logger.Info("开始从Sqlite拉取Dat200Rh数据到Mes中间表");

                using (var scope = App._container.BeginLifetimeScope())
                {
                    var sqliteCtx = scope.Resolve<SqliteDbContext>();
                    var oracleCtx = scope.Resolve<OracleDbContext>();

                    // 检测结果上传KJ_VULKAMETER_TEST_RESULT表
                    // 查询本地sqlite没有同步的记录
                    var sqliteRhData = sqliteCtx.Db.Queryable<SqliteDat200Rh>().Where(item => item.RECEIVE_FLAG == "PENDING").ToList();
                  
                    List<KJ_VULKAMETER_TEST_RESULT> testDataList = new List<KJ_VULKAMETER_TEST_RESULT>();
                    List<KJ_PROCESS_STEP> processStepList = new List<KJ_PROCESS_STEP>();

                    // 数据处理
                    if (sqliteRhData.Any())
                    {                    
                        foreach (var item in sqliteRhData)
                        {
                            var testData = new KJ_VULKAMETER_TEST_RESULT()
                            {
                                EQP =item.F12, //机台
                                LOT_NUMBER = item.F14,//批号
                                PART_NUMBER= item.F10,// 胶号
                                CHECI_NUMBER = item.F150,//车次
                                USER_CODE = item.F6, //工号
                                SHIFT  = item.F11,//班次
                                RECORD_DATE = DateTime.Now,
                                RESULT = item.F16, //结果
                                RECEIVE_FLAG = __REMOTE_SYNC_STATE_PENDING,
                            };
                            testDataList.Add(testData);

                            string[] val1Parts = item.DatVal_1.Split(new[] { '/' }); //刻度
                            string[] val2Parts = item.DatVal_2.Split(new[] { '/' }); //硫化数据
                            string[] val7Parts = item.DatVal_7.Split(new[] { '/' }); //上模温度
                            string[] val8Parts = item.DatVal_8.Split(new[] { '/' }); //下模温度

                            for (int i = 0; i < val1Parts.Length; i++)
                            {
                                var step = new KJ_PROCESS_STEP
                                {
                                    EQP = item.F12, //机台
                                    LOT_NUMBER = item.F14,//批号
                                    PART_NUMBER = item.F10,// 胶号
                                    CHECI_NUMBER = item.F150,//车次
                                    RECORD_DATE = DateTime.Now,
                                    RECORD1 = val1Parts[i].Trim(), //刻度
                                    RECORD2 = val2Parts[i].Trim(), //硫化数据
                                    RECORD3 = val7Parts[i].Trim(), //上模温度
                                    RECORD4 = val8Parts[i].Trim(), //下模温度
                                    RECEIVE_FLAG = __REMOTE_SYNC_STATE_PENDING,
                                };

                                processStepList.Add(step);
                            }
                        }
                    }
                    else
                    {
                        _logger.Info("Sqlite没有需要同步的Dat200Rh数据");
                        return;
                    }

                    // 事务处理
                    try
                    {
                        // ======================================
                        // 第一步：执行 Oracle事务操作（先开启，便于后续回滚）
                        // ======================================
                        DbConnection oracleConn = oracleCtx.Db.Ado.MasterPool.Get().Value;
                        try
                        {
                            oracleTrans = oracleConn.BeginTransaction();
                            // 新增检测标准记录到KJ_VULKAMETER_TEST_RESULT
                            oracleCtx.Db.Insert<KJ_VULKAMETER_TEST_RESULT>().WithTransaction(oracleTrans).AppendData(testDataList).ExecuteAffrows();
                            // 新增检测标准记录到KJ_PROCESS_STEP
                            oracleCtx.Db.Insert<KJ_PROCESS_STEP>().WithTransaction(oracleTrans).AppendData(processStepList).ExecuteAffrows();
                        }
                        catch (Exception ex)
                        {
                            oracleConn.Dispose();
                            throw new Exception("Oracle 操作失败：" + ex.Message, ex);
                        }

                        // ======================================
                        // 第二步：执行 SQLite 事务操作（Access 成功后再执行）
                        // ======================================
                        var sqliteConn = sqliteCtx.Db.Ado.MasterPool.Get().Value; // 获取 SQLite 连接
                        try
                        {

                            if (sqliteConn.State == System.Data.ConnectionState.Closed)
                            {
                                sqliteConn.Open();
                            }
                            // 开启 SQLite 本地事务（仅作用于当前数据库）
                            sqliteTrans = sqliteConn.BeginTransaction();


                            // 更新 SQLite 同步状态（验证更新行数）
                            long updateCount2 = sqliteCtx.Db.Update<SqliteDat200Rh>()
                                .SetSource(sqliteRhData,item=>item.F0)
                                .Set(x => x.RECEIVE_FLAG, __REMOTE_SYNC_STATE_COMPLETE)
                                .WithTransaction(sqliteTrans) // 关键：绑定事务上下文
                                .ExecuteAffrows();

                            // SQLite 操作成功，提交 SQLite 事务
                            sqliteTrans.Commit();
                            sqliteTrans.Dispose();
                            sqliteConn.Dispose();

                            // ======================================
                            // 第三步：Access 最终提交（所有操作都成功）
                            // ======================================
                            oracleTrans.Commit();
                            oracleTrans.Dispose();
                            oracleConn.Dispose();

                            _logger.Info(" 推送sqlite检测数据到oracle成功");
                        }
                        catch (Exception ex)
                        {
                            // SQLite 操作失败：手动回滚 Access 事务 + 回滚 SQLite 事务
                            if (sqliteTrans != null) sqliteTrans.Rollback();
                            if (oracleTrans != null) oracleTrans.Rollback(); 

                            // 释放资源
                            sqliteTrans?.Dispose();
                            sqliteConn.Dispose();
                            oracleTrans?.Dispose();
                            oracleConn.Dispose();

                            throw new Exception("SQLite 操作失败，已回滚 Oracle 事务：" + ex.Message, ex);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("跨库事务失败，已回滚事务：" + ex.Message, ex);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Info("跨库事务失败，已回滚事务",ex);
            }
        }


        #endregion


        #region  同步本地开班检点数据到oracle

        public void PushStartWorkCheckPointToOracle()
        {
            try
            {
                _logger.Info("开始从Sqlite拉取开班检点数据到Mes中间表");

                using (var scope = App._container.BeginLifetimeScope())
                {
                    var sqliteCtx = scope.Resolve<SqliteDbContext>();
                    var oracleCtx = scope.Resolve<OracleDbContext>();

                    // 查询本地sqlite没有同步的记录
                    var sqliteHeadData = sqliteCtx.Db.Queryable<Sqlite_KJ_EXAMINE_HEADER>().Where(item => item.RECEIVE_FLAG == "PENDING").ToList();
                    var sqliteLineData = sqliteCtx.Db.Queryable<Sqlite_KJ_EXAMINE_LINE>().Where(item => item.RECEIVE_FLAG == "PENDING").ToList();

                    // 数据转化
                    AutoMapperConfig.Init();
                    var headList = Mapper.Map<List<KJ_EXAMINE_HEADER>>(sqliteHeadData);
                    var lineList = Mapper.Map<List<KJ_EXAMINE_LINE>>(sqliteLineData);
                    // 事务处理
                    try
                    {
                        // ======================================
                        // 第一步：执行 Oracle事务操作（先开启，便于后续回滚）
                        // ======================================
                        DbConnection oracleConn = oracleCtx.Db.Ado.MasterPool.Get().Value;
                        try
                        {
                            if (oracleConn.State == System.Data.ConnectionState.Closed)
                            {
                                oracleConn.Open();
                            }
                            oracleTrans = oracleConn.BeginTransaction();
                            // 新增检点头表
                            oracleCtx.Db.Insert<KJ_EXAMINE_HEADER>().WithTransaction(oracleTrans).AppendData(headList).ExecuteAffrows();
                            // 新增检点行表
                            oracleCtx.Db.Insert<KJ_EXAMINE_LINE>().WithTransaction(oracleTrans).AppendData(lineList).ExecuteAffrows();
                        }
                        catch (Exception ex)
                        {
                            // Access 操作失败，直接释放连接并抛异常
                            oracleConn.Dispose();
                            throw new Exception("Oracle 操作失败：" + ex.Message, ex);
                        }

                        // ======================================
                        // 第二步：执行 SQLite 事务操作（Access 成功后再执行）
                        // ======================================
                        var sqliteConn = sqliteCtx.Db.Ado.MasterPool.Get().Value; // 获取 SQLite 连接
                        try
                        {
                            if (sqliteConn.State == System.Data.ConnectionState.Closed)
                            {
                                sqliteConn.Open();
                            }
                            // 开启 SQLite 本地事务（仅作用于当前数据库）
                            sqliteTrans = sqliteConn.BeginTransaction();


                            // 更新 SQLite 头表同步状态
                            sqliteCtx.Db.Update<Sqlite_KJ_EXAMINE_HEADER>()
                                .SetSource(sqliteHeadData, item => item.LJ_ID)
                                .Set(x => x.RECEIVE_FLAG, __REMOTE_SYNC_STATE_COMPLETE)
                                .WithTransaction(sqliteTrans) // 关键：绑定事务上下文
                                .ExecuteAffrows();

                            // 更新 SQLite 行表同步状态
                           sqliteCtx.Db.Update<Sqlite_KJ_EXAMINE_LINE>()
                                .SetSource(sqliteLineData, item => item.LJ_ID)
                                .Set(x => x.RECEIVE_FLAG, __REMOTE_SYNC_STATE_COMPLETE)
                                .WithTransaction(sqliteTrans) // 关键：绑定事务上下文
                                .ExecuteAffrows();

                            // SQLite 操作成功，提交 SQLite 事务
                            sqliteTrans.Commit();
                            sqliteTrans.Dispose();
                            sqliteConn.Dispose();

                            // ======================================
                            // 第三步：最终提交（所有操作都成功）
                            // ======================================
                            oracleTrans.Commit();
                            oracleTrans.Dispose();
                            oracleConn.Dispose();

                            _logger.Info(" 推送sqlite检测数据到Mes成功");
                        }
                        catch (Exception ex)
                        {
                            // SQLite 操作失败：手动回滚 Access 事务 + 回滚 SQLite 事务
                            if (sqliteTrans != null) sqliteTrans.Rollback();
                            if (oracleTrans != null) oracleTrans.Rollback();

                            // 释放资源
                            sqliteTrans?.Dispose();
                            sqliteConn.Dispose();
                            oracleTrans?.Dispose();
                            oracleConn.Dispose();

                            throw new Exception("SQLite 操作失败，已回滚Mes事务：" + ex.Message, ex);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("跨库事务失败，已回滚事务：" + ex.Message, ex);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
        #endregion

    }
}